package net.zjitc.security.filter;

import com.alibaba.druid.util.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.zjitc.common.ResponseResult;
import net.zjitc.security.service.UserDeatilsServiceImpl;
import net.zjitc.security.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private UserDeatilsServiceImpl userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //先获得header: Authorization :token

        //如果null，则没有登录

        //如果不为空，再去解析token(token是否有效，token过期)

        //放行

        //获得Authorization头部信息
        String token = request.getHeader(jwtTokenUtil.getTokenHeader());
        //如果带了token过来，则说明已经登录过
        if (!StringUtils.isEmpty(token)&&!token.equals("null")) {
            String username = null;
            try {
                //从token中获取username
                username = jwtTokenUtil.getUsernameFromToken(token);
            } catch (Exception e) {
                //token异常的处理
                tokenError(response);
                return;
            }

            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                //token --：db
                //redis....
                //
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                //认证是否成功
                if (jwtTokenUtil.validateToken(token, userDetails)) {
                    // 将用户信息存入 authentication，方便后续校验
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    // 将 authentication 存入 ThreadLocal，方便后续获取用户信息
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                } else {
                    tokenError(response);
                    return;
                }
            }
        }
        filterChain.doFilter(request, response);
    }

    private void tokenError(HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        ServletOutputStream out = response.getOutputStream();
        ResponseResult<Object> result = new ResponseResult<>();
        result.setError("token无效");
        String str = new ObjectMapper().writeValueAsString(result);
        out.write(str.getBytes(StandardCharsets.UTF_8));
        out.flush();
        out.close();
    }
}
